package com.um.springboot.starter.utils;

import lombok.extern.slf4j.Slf4j;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

@Slf4j
public class DateUtil {


	/**
	 * 验证是否是有效的日期
	 * @param fromDate
	 * @param toDate
	 * @param dates
	 * @return
	 */
	public static boolean isValidateDate(String fromDate, String toDate,
									   String[] dates) {
		if ((fromDate == null) || (fromDate.trim().length() == 0))
			return false;
		if ((toDate == null) || (toDate.trim().length() == 0))
			return false;
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Date begin = null;
		Date end = null;
		try {
			begin = format.parse(fromDate);
			end = format.parse(toDate);
			if (begin.after(end))
				return false;
			dates[0] = format.format(begin);
			dates[1] = format.format(end);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	public static String getTimeString(Timestamp tsp) {
		if (tsp == null)
			return "";
		return getTimeString(new Date(tsp.getTime()));
	}

	public static String getTimeString(Date date) {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return formatter.format(date).trim();
	}

	public static String getDateString(Date date) {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		return formatter.format(date).trim();
	}

	public static String getNowDateString() {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		return formatter.format(new Date()).trim();
	}

	public static String getDatetimeString() {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
		return formatter.format(new Date()).trim();
	}

	public static String getDateString(Date date, String format) {
		SimpleDateFormat formatter = new SimpleDateFormat(format);
		return formatter.format(date).trim();
	}

	public static String getBetweenDate(String property, Date start, Date end) {
		String ext = " " + property + " >='" + DateUtil.getDateString(start)
				+ "' and " + property + " <='" + DateUtil.getDateString(end)
				+ "'";
		return ext;
	}

	public static int getDateInt(Date date) {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
		return Integer.parseInt(formatter.format(date).trim());
	}

	public static String to_char(Timestamp tsp, String format) {
		if (tsp == null)
			return "";
		return to_char(new Date(tsp.getTime()), format);
	}

	public static String to_char(Date date, String format) {
		SimpleDateFormat formatter = new SimpleDateFormat(format);
		return formatter.format(date).trim();
	}

	public static Timestamp to_timestamp(String date) {
		return new Timestamp(to_date(date).getTime());
	}

	public static Date stringToDate(String dateText, String format) {
		if (dateText == null) {
			return null;
		}
		DateFormat df = null;
		try {
			if (format == null)
				df = new SimpleDateFormat();
			else {
				df = new SimpleDateFormat(format);
			}

			df.setLenient(false);
			return df.parse(dateText);
		} catch (ParseException localParseException) {
		}
		return null;
	}

	public static Date to_date(String date) {
		/*Calendar cd = Calendar.getInstance();
		StringTokenizer token = new StringTokenizer(date, "-/ :");
		if (token.hasMoreTokens())
			cd.set(1, Integer.parseInt(token.nextToken()));
		else {
			cd.set(1, 1970);
		}
		if (token.hasMoreTokens())
			cd.set(2, Integer.parseInt(token.nextToken()) - 1);
		else {
			cd.set(2, 0);
		}
		if (token.hasMoreTokens())
			cd.set(5, Integer.parseInt(token.nextToken()));
		else {
			cd.set(5, 1);
		}
		if (token.hasMoreTokens())
			cd.set(11, Integer.parseInt(token.nextToken()));
		else {
			cd.set(11, 0);
		}
		if (token.hasMoreTokens())
			cd.set(12, Integer.parseInt(token.nextToken()));
		else {
			cd.set(12, 0);
		}
		if (token.hasMoreTokens())
			cd.set(13, Integer.parseInt(token.nextToken()));
		else {
			cd.set(13, 0);
		}
		if (token.hasMoreTokens())
			cd.set(14, Integer.parseInt(token.nextToken()));
		else {
			cd.set(14, 0);
		}
		return cd.getTime();*/
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

		if(date.length() == 10){
			df = new SimpleDateFormat("yyyy-MM-dd");
		}else if(StringUtil.getTrim(date).indexOf("T") < 0){
			if(date.length() == 13){
				df = new SimpleDateFormat("yyyy-MM-dd HH");
			}else if(date.length() == 16){
				df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			}else {
				df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			}
		}else if(date.length() == 13){
			df = new SimpleDateFormat("yyyy-MM-dd'T'HH");
		}else if(date.length() == 16){
			df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
		}else if(date.length() == 19){
			df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
		}

		try {
			return df.parse(date);
		} catch (ParseException e) {
			return null;
		}
	}

	/**
	 * 格式化日期
	 * @param value
	 * @return
	 */
	public static Date parse(String value){
		if(value.length() == 10){
			return to_date(value);
		}else if(value.indexOf("T") > 0 ){
			DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
			Date date;
			try {
				date = df.parse(StringUtil.getTrim(value));
			} catch (ParseException e) {
				return null;
			}
			return date;
		}
		return null;
	}

	public static final String[] getDateRange(int selType) {
		String startDate = null;
		String endDate = null;

		Calendar cd = Calendar.getInstance();
		int year = cd.get(1);
		int month = cd.get(2) + 1;
		Calendar cdTmp = Calendar.getInstance();

		switch (selType) {
			case 1:
				int i = cd.get(7) - 1;
				cdTmp.setTime(new Date(cd.getTime().getTime() - i * 3600 * 24
						* 1000));
				startDate = cdTmp.get(1) + "-" + (cdTmp.get(2) + 1) + "-"
						+ cdTmp.get(5);
				i = 7 - cd.get(7);
				cdTmp.setTime(new Date(cd.getTime().getTime() + i * 3600 * 24
						* 1000));
				endDate = cdTmp.get(1) + "-" + (cdTmp.get(2) + 1) + "-"
						+ cdTmp.get(5);
				break;
			case 2:
				startDate = year + "-" + month + "-01";
				switch (month) {
					case 1:
					case 3:
					case 5:
					case 7:
					case 8:
					case 10:
					case 12:
						endDate = year + "-" + month + "-31";
						break;
					case 2:
						if (isLeapYear(year))
							endDate = year + "-" + month + "-29";
						else
							endDate = year + "-" + month + "-28";
						break;
					case 4:
					case 6:
					case 9:
					case 11:
					default:
						endDate = year + "-" + month + "-30";
				}
				break;
			case 3:
				startDate = year + "-01-01";
				endDate = year + "-12-31";
				break;
			default:
				startDate = "2000-01-01";
				endDate = "2100-01-01";
		}
		return new String[] { startDate, endDate };
	}

	public static final boolean isLeapYear(int y) {
		if (y % 4 == 0) {
			if (y % 100 == 0) {
				return y % 400 == 0;
			}

			return true;
		}

		return false;
	}

	public static Date dateIncreaseByMinute(Date date, int minutes) {
		Calendar cal = GregorianCalendar.getInstance(TimeZone
				.getTimeZone("GMT"));
		cal.setTime(date);
		cal.add(Calendar.MINUTE, minutes);

		return cal.getTime();
	}

	public static Date dateIncreaseByHour(Date date, int hours) {
		Calendar cal = GregorianCalendar.getInstance(TimeZone
				.getTimeZone("GMT"));
		cal.setTime(date);
		cal.add(Calendar.HOUR, hours);

		return cal.getTime();
	}

	public static Date dateIncreaseByDay(Date date, int days) {
		Calendar cal = GregorianCalendar.getInstance(TimeZone
				.getTimeZone("GMT"));
		cal.setTime(date);
		cal.add(Calendar.DATE, days);

		return cal.getTime();
	}

	public static Date dateIncreaseByMonth(Date date, int mnt) {
		Calendar cal = GregorianCalendar.getInstance(TimeZone
				.getTimeZone("GMT"));
		cal.setTime(date);
		cal.add(Calendar.MONTH, mnt);

		return cal.getTime();
	}

	public static Date dateIncreaseByYear(Date date, int mnt) {
		Calendar cal = GregorianCalendar.getInstance(TimeZone
				.getTimeZone("GMT"));
		cal.setTime(date);
		cal.add(Calendar.YEAR, mnt);

		return cal.getTime();
	}

	public static final Date getThisweekFirst(Date early) {
		Calendar c1 = Calendar.getInstance();
		c1.setTime(early);
		int week = c1.get(7);
		int firstw = -1 * (week - 1);
		Date weekFirst = dateIncreaseByDay(early, firstw);
		return weekFirst;
	}

	public static final Date firstdateIncreaseByWeek(Date early, int weeks) {
		Date firstDate = getThisweekFirst(early);
		firstDate = dateIncreaseByDay(firstDate, weeks * 7);
		return firstDate;
	}

	public static final int monthsIndays(Date early, Date late) {
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(early);
		c2.setTime(late);
		int earlyYear = c1.get(1);
		int earlyMonth = c1.get(2);
		int lateYear = c2.get(1);
		int lateMonth = c2.get(2);
		int months = (lateYear - earlyYear) * 12 + lateMonth - earlyMonth + 1;
		return months;
	}

	public static final int weeksIndays(Date early, Date late) {
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(early);
		c2.setTime(late);
		int days = daysBetween(c1, c2) + 1;
		int earlyweek = c1.get(7);
		int lateweek = c2.get(7);
		int weeks = days / 7;
		int weekst = days % 7;
		if (weekst == 0)
			return weeks;
		if (lateweek >= earlyweek) {
			return weeks + 1;
		}
		return weeks + 2;
	}

	public static final int daysBetween(Date early, Date late) {
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(early);
		c2.setTime(late);

		return daysBetween(c1, c2);
	}

	public static final int daysBetween(Calendar early, Calendar late) {
		return (int) (toJulian(late) - toJulian(early));
	}

	public static final float toJulian(Calendar c) {
		int Y = c.get(1);
		int M = c.get(2);
		int D = c.get(5);
		int A = Y / 100;
		int B = A / 4;
		int C = 2 - A + B;
		float E = (int) (365.25F * (Y + 4716));
		float F = (int) (30.6001F * (M + 1));
		float JD = C + D + E + F - 1524.5F;

		return JD;
	}

	/**
	 * 是否是润年
	 * @param Year 年份
	 * @return
	 */
	public static final boolean checkLeapYear(int Year) {
		boolean isLeapYear = false;
		if ((Year % 4 == 0) && (Year % 100 != 0)) {
			isLeapYear = true;
		}
		if (Year % 400 == 0)
			isLeapYear = true;
		else if (Year % 4 != 0) {
			isLeapYear = false;
		}
		return isLeapYear;
	}

	public static final int checkMonth(int Month, int Year) {
		int Dates = 0;
		if ((Month < 0) || (Month > 12)) {
			//Month Error
		}
		if ((Month == 1) || (Month == 3) || (Month == 5) || (Month == 7)
				|| (Month == 8) || (Month == 10) || (Month == 12)) {
			Dates = 31;
		}
		if ((Month == 2) && (checkLeapYear(Year))) {
			Dates = 29;
		}
		if ((Month == 2) && (!checkLeapYear(Year))) {
			Dates = 28;
		}
		if ((Month == 4) || (Month == 6) || (Month == 9) || (Month == 11)) {
			Dates = 30;
		}
		return Dates;
	}


	/**
	 * 获得参数日期和当前日期的时间差
	 *
	 * @param endDay
	 * @return
	 */
	public static long getDateDiff(Object endDay) {
		long diff = 0;
		try {
			Date startD = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(String.valueOf(getNowDate()));
			Date endD = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(String.valueOf(endDay));
			diff = (endD.getTime() - startD.getTime()) / (24 * 60 * 60 * 1000);
		} catch (ParseException e) {
			log.error("", e);
		}
		return diff;
	}

	/**
	 * 获得当前日期与时间
	 * @return
	 */
	public static String getNowDatetime() {
		Calendar beginCal = Calendar.getInstance();
		SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return f.format(beginCal.getTime());
	}

	/**
	 * 获得当前日期
	 * @return
	 */
	public static Object getNowDate() {
		Calendar beginCal = Calendar.getInstance();
		SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
		return f.format(beginCal.getTime());
	}

	public static String getOldDate(int distanceDay) {
		SimpleDateFormat dft = new SimpleDateFormat("yyyy-MM-dd");
		Date beginDate = new Date();
		Calendar date = Calendar.getInstance();
		date.setTime(beginDate);
		date.set(Calendar.DATE, date.get(Calendar.DATE) + distanceDay);
		Date endDate = null;
		try {
			endDate = dft.parse(dft.format(date.getTime()));
		} catch (ParseException e) {
			log.error("", e);
		}
		return dft.format(endDate);
	}

	/**
	 *
	 * @param startDate
	 * @param period
	 * @return
	 */
	public static Object getDateByPeriod(Object startDate, Object period) {
		try {
			DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

			Date startD = df.parse((String.valueOf(startDate)));
			return dateIncreaseByMonth(startD,
					(period != null ? Integer.valueOf(String.valueOf(period))
							: 0));
		} catch (Exception e) {
			log.error("", e);
			return getNowDate();
		}
	}

	/**
	 * 获得参数日期距当前日期的时间
	 * @param datestr 字符串时间
	 * @return
	 */
	public static String getTimeDuration(String datestr) {
		Date date = to_date(datestr);
		return getTimeDurationByDate(date);
	}

	/**
	 * 获得参数日期距当前日期的时间
	 * @param date 时间
	 * @return
	 */
	public static String getTimeDurationByDate(Date date) {
		long time = date.getTime();
		long nowTime = new Date().getTime();
		long diffTime = (nowTime - time) / 1000;

		String result = "";
		if (diffTime < 60) {
			result = diffTime + "秒之前";
		} else if (diffTime / 60 < 60) {
			result = (diffTime / 60) + "分钟之前";
		} else if (diffTime / 3600 < 24) {
			result = (diffTime / 3600) + "小时之前";
		} else if ((diffTime / 3600) / 24 < 2) {
			result = "昨天";
		} else if ((diffTime / 3600) / 24 < 3) {
			result = "前天";
		} else {
			result = getDateString(date, "yyyy-MM-dd");
		}

		return result;
	}


	/**
	 * 判断两个日期的大小
	 * @param DATE1 日期1
	 * @param DATE2 日期2
	 * @param dateFormat 字符串格式
	 * @return 返回 1：DATE1时间比较晚 -1：DATE2时间比较晚 0：两个时间相等
	 */
	public static Integer compareDate(String DATE1, String DATE2, String dateFormat) {
		DateFormat df = new SimpleDateFormat(dateFormat);
		try {
			Date dt1 = df.parse(DATE1);
			Date dt2 = df.parse(DATE2);
			if (dt1.getTime() > dt2.getTime()) {
				return 1;
			} else if (dt1.getTime() < dt2.getTime()) {
				return -1;
			} else {
				return 0;
			}
		} catch (Exception e) {

		}
		return null;
	}

}